package org.ifilm.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.ifilm.model.Project;
import org.ifilm.model.ProjectComment;
import org.ifilm.model.ProjectRating;
import org.ifilm.model.User;
import org.ifilm.model.UserJobPosting;
import org.springframework.stereotype.Repository;

/**
 * 
 * @author Mustafa Genç
 *
 */
@Repository
public class ProjectDaoImpl implements ProjectDao {
	
	@PersistenceContext
	private EntityManager entityManager;
	
	@Override
	public Project createProject(Project project) {
		return entityManager.merge(project);
	}
	
	@Override
	public ProjectRating createProjectRating(ProjectRating projectRating) {
		return entityManager.merge(projectRating);
	}
	
	@Override
	public ProjectComment createProjectComment(ProjectComment projectComment) {
		return entityManager.merge(projectComment);
	};
	
	@Override
	public Project getProject(Long id) {
		try {
			Query query = entityManager.createQuery(getProjectQuery());
			query.setParameter("id", id);
			return (Project) query.getSingleResult();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public String getProjectQuery() {
		StringBuilder strBuild = new StringBuilder();
		strBuild.append("select p from project p where p.id=:id");
		return strBuild.toString();
	}
	
	@Override
	public List<UserJobPosting> searchPostingsByUserType(Integer page, Integer max, List<String> userTypeName) {
		try {
			Query query = entityManager.createQuery(searchProjectsQuery());
			query.setParameter("type", userTypeName);
			query.setFirstResult((page - 1) * max);
			query.setMaxResults(max);
			return (List<UserJobPosting>) query.getResultList();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	private String searchProjectsQuery() {
		StringBuilder strBuild = new StringBuilder();
		strBuild.append("select userpost from jobposting userpost where userpost.type in (:type) " +
				"and userpost.totalNeeded > userpost.totalAccepted " +
				"order by userpost.project.id DESC");
		return strBuild.toString();
	}
	
	@Override
	public void editProject(Project project){
		entityManager.merge(project);
	}
	
	@Override
	public List<Project> listProjects(Integer page, Integer max) {
		try {
			Query query = entityManager.createQuery(listAllProjectsQuery());
			query.setFirstResult((page - 1) * max);
			query.setMaxResults(max);
			return (List<Project>) query.getResultList();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	private String listAllProjectsQuery() {
		StringBuilder strBuild = new StringBuilder();
		strBuild.append("select p from project p order by p.id DESC");
		return strBuild.toString();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Project> listUserProjects(Long userId, Integer page, Integer max) {
		try {
			Query query = entityManager.createQuery(listUserProjectsQuery());
			query.setParameter("userId", userId);
			query.setFirstResult((page - 1) * max);
			query.setMaxResults(max);
			return (List<Project>) query.getResultList();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	private String listUserProjectsQuery() {
		StringBuilder strBuild = new StringBuilder();
		strBuild.append("select p from project p where (p.creator.id =:userId) order by p.id DESC");
		return strBuild.toString();
	}
	
	@Override
	public ProjectRating getProjectRate(Long projectId, User rater) {
		try {
			Query query = entityManager.createQuery(getProjectRateQuery());
			query.setParameter("rater", rater);
			query.setParameter("projectId", projectId);
			return (ProjectRating)query.getSingleResult();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	private String getProjectRateQuery() {
		StringBuilder strBuild = new StringBuilder();
		strBuild.append("select p from projectrating p where p.rater=:rater and p.ratedProject.id=:projectId");
		return strBuild.toString();
	}

	@Override
	public List<ProjectComment> getComments(Long projectId) {
		try {
			Query query = entityManager.createQuery(getCommentsQuery());
			query.setParameter("projectId", projectId);
			return (List<ProjectComment>)query.getResultList();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	private String getCommentsQuery() {
		StringBuilder strBuild = new StringBuilder();
		strBuild.append("select pc from projectcomment pc where pc.commented.id=:projectId");
		return strBuild.toString();
	}

	@Override
	public List<UserJobPosting> searchByUserDetail(User user) {
		try {
			Query query = entityManager.createQuery(searchByUserDetailQuery());
			query.setParameter("type", user.getUserType() );
			
			Integer height = user.getHeight();
			Integer weight = user.getWeight();
			Integer age = user.getAge();
			
			if (height == null) {
				query.setParameter("height1", 0);
				query.setParameter("height2", 999);
			} else {
				query.setParameter("height1", height);
				query.setParameter("height2", height);
			}
			
			if (weight == null) {
				query.setParameter("weight1", 0);
				query.setParameter("weight2", 999);
			} else {
				query.setParameter("weight1", weight);
				query.setParameter("weight2", weight);
			}
			
			if (age == null) {
				query.setParameter("age1", 0);
				query.setParameter("age2", 999);
			} else {
				query.setParameter("age1", age);
				query.setParameter("age2", age);
			}
			
			query.setParameter("eyeColor", user.getEyeColor());
			query.setParameter("hairColor", user.getHairColor());
			return (List<UserJobPosting>)query.getResultList();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	private String searchByUserDetailQuery() {
		StringBuilder strBuild = new StringBuilder();
		strBuild.append("select userpost from jobposting userpost " +
				"where userpost.type in (:type) " +
				"and userpost.maxHeight >:height1 and userpost.minHeight <:height2 " +
				"and userpost.maxWeight >:weight1 and userpost.minWeight <:weight2 " +
				"and userpost.maxAge >:age1 and userpost.minAge <:age2 " +
				"and (userpost.eyeColor='any' or userpost.eyeColor=:eyeColor) " +
				"and (userpost.hairColor='any' or userpost.hairColor=:hairColor) " +
				"and userpost.totalNeeded > userpost.totalAccepted " +
				"order by userpost.project.id DESC");
		return strBuild.toString();
	}

	
	public User getUserById(Long id) {
		try {
			Query query = entityManager.createQuery(getUserByIdQuery());
			query.setParameter("id", id);

			return (User) query.getSingleResult();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	private String getUserByIdQuery() {
		StringBuilder strBuild = new StringBuilder();
		strBuild.append("select u from user u where u.id=:id");
		return strBuild.toString();
	}
}